
from WtfEngine import *;
import WtfGui;
from scripts import *;
from Util import *;
import Orders;

gController = 0;

class Player:
	def __init__(self, soc):
		self.society = soc;
		self.windows = [];
		
	def IsLocal(self):
		return True;

	def StartTurn(self, ctrl):
		# Restore windows
		for wnd in self.windows:
			ctrl.gameWm.AddWindow(wnd, True);
		
	def EndTurn(self, ctrl):
		# Save and remove all windows
		self.windows = filter(lambda w: ctrl.gameWm.HasChild(w), self.windows);
		for wnd in self.windows:
			wnd.Remove();
		
	def AddWindow(self, win):
		self.windows.append(win);
		if Controller.GetInst().currentPlayer == self:
			Controller.GetInst().gameWm.AddWindow(win, True);

class TbsGameState(CustomGameState):
	def __init__(self, camera):
		CustomGameState.__init__(self);
		self.camera = camera;
	
	def Enable(self):
		Renderer.GetInst().camera = self.camera;
		
		
# Manages and issues orders to the selected units
class Controller:
	def __init__(self):
		global gController;
		
		self.selectedUnits = [];
		self.listeners = [];
		
		self.commonOrders = [];
		self.orders = [Orders.StopOrder()];
		
		gController = self;
		
		Orders.Manager();
	
	def GetStartGameOptions(self):
		return DictToObject({
				'players': []
			});

	def StartGame(self, game, wm, opts):
		self.game = game;
		self.gameWm = wm;
		
		self.onPlayerStartTurn = [];
		
		# Camera setup
		camOpts = PannableCameraOptions();
		self.camera = PannableCamera(camOpts, Vector(0, 100, 100), Vector(0, -100, -100));
		
		# Push a fresh game state
		self.gameState = Kernel.GetInst().PushGameState(TbsGameState(self.camera));
		
		self.camera.BindToKeyboardAndMouse();
		
		#self.unitSelection = WtfRts.UnitSelection();
		#self.unitSelection.onChange = Function(lambda: self.OnUnitSelect());
		#self.unitSelection.Init();
		
		# Start turn backdrop
		self.startTurnWm = WtfGui.WindowManager();
		self.startTurnWm.dlg = WtfGui.LayoutContainer(WtfGui.LayoutContainerCreationOptions(), 1);
		self.startTurnWm.dlg.padding = self.startTurnWm.dlg.paddingRB = iVector2D(5, 5);
		self.startTurnWm.AddChild(WtfGui.LayoutPositioner(self.startTurnWm.dlg,
			WtfGui.CentrePositioner(), WtfGui.CentrePositioner()));
		font = WtfGui.Font("v_gui_font");
		self.startTurnWm.lbl = WtfGui.Label("", font);
		self.startTurnWm.btn = WtfGui.Button(Function(lambda: self.startTurnWm.WmToggle()),
			"Start Turn", font);
		self.startTurnWm.btn.ExpandToText();
		self.startTurnWm.dlg.AddChild(self.startTurnWm.lbl);
		self.startTurnWm.dlg.AddChild(self.startTurnWm.btn);
		
		# Get local players
		self.localPlayers = [];
		for plyr in opts.players:
			if plyr.IsLocal():
				self.localPlayers.append(plyr);
				plyr.localPlayerIndex = len(self.localPlayers) - 1;
		
		wm.Init();
		
		self.OnGameSync(self.StartTurn);
		game.StartGame(opts);
	
	def StartTurn(self):
		self.currentPlayer = self.localPlayers[0];
		self.PlayerStartTurn();
		
	def PlayerStartTurn(self):
		self.currentPlayer.StartTurn(self);
		
		map(lambda f: f(self.currentPlayer), self.onPlayerStartTurn);
		
		self.startTurnWm.lbl.caption = ("Player " + str(self.currentPlayer.localPlayerIndex)
			+ ", it is your turn.");
		self.startTurnWm.lbl.ExpandToText();
		#self.startTurnWm.WmToggle();
		
	
	def EndTurn(self):
		self.currentPlayer.EndTurn(self);
		
		nextPlayerIdx = self.currentPlayer.localPlayerIndex + 1;
		if nextPlayerIdx < len(self.localPlayers):
			self.currentPlayer = self.localPlayers[nextPlayerIdx];
			self.PlayerStartTurn();
		else:
			self.OnGameSync(self.StartTurn);
			DebugPrint("End of turn");
			self.game.EndTurn();
	
		
	def GetPlayerSociety(self):
		return self.currentPlayer.society;
	
	def GetGlobalMarketData(self):
		return self.currentPlayer.society.GetCentralMarket().GetMarketData();
		
	def OnUnitSelect(self):
		DebugPrint("Selection Change");
		
		# Refresh unit selection
		self.selectedUnits = self.unitSelection.selection;
		
		# Enumerate intersection of orders
		if len(self.selectedUnits) > 0:
			self.orders = Orders.Manager.GetInst().allOrders.values();
			map(lambda unit: DebugPrint(unit.__class__.__name__), self.selectedUnits);
		else:
			self.orders = [];
		
		
		# Notify listeners
		map(lambda f: f(), self.listeners);
	
	
	def OnGameSync(self, f, persistent = False):
		"""\
Registers a callback function for when the game is synchronized (on end of turns, for e.g.)"""
		f();
		
	def SetOrders(self, orders):
		self.orders = filter(lambda order: orders.count(order) > 0, self.orders);
		
	def InvokeOrder(self, order):
		return 0;
		
	def Listen(self, f):
		self.listeners.append(f);
	
	def GetInst():
		assert(gController != 0);
		return gController;
	GetInst = StaticM(GetInst);